//Binary_conversion_helper.c
#define Binary_conversion_helper_C
#include "Binary_conversion_helper.h"


typedef unsigned char * byte_pointer;


void show_bytes(byte_pointer bytes,size_t len);

void B_add_one(char *B);                    //二进制加1 (最高位符号位不变)
void B_sub_one(char *B);                    //二进制减1 (最高位符号位不变)
void B_original_to_B_inverse(char *B_original);








void show_bytes(byte_pointer bytes,size_t len){
  size_t i;
  for (i = 0; i < len; i++) 
    printf("%.2x ",bytes[i]);
  printf("\n");
}


/**
  * @brief  以十六进制形式打印整型变量的字节位码
  * @param  int
  * @retval NULL
  */
void show_int_bytes(int x) {
  show_bytes((byte_pointer)&x, sizeof(int));
}

void show_float_bytes(float x) {
  show_bytes((byte_pointer)&x, sizeof(float));
}

void show_pointer_bytes(void *x) {
  show_bytes((byte_pointer)x, sizeof(void *));
}

//计算机的数据以补码形式在内存中存储
//对于正数，其原,反,补码就是它本身的二进制表示

//Decimal is converted to complement
const char *D_to_B_complement(int num) {
  int num_bits = sizeof(num) * 8;
  int num_spaces = (num_bits / 4) - 1;
  char *B_complement = (char *)calloc(num_bits + num_spaces + 1, sizeof(char));
  if (B_complement) {
      int space_count = 0;
      int index = 0;
      for (int i = num_bits - 1; i >= 0; i--) {
          B_complement[index++] = (((unsigned long long)(num) >> i) & 1) + '0';
          space_count++;
          if (space_count % 4 == 0 && i != 0) {
              B_complement[index++] = ' ';
          }
      }
      B_complement[num_bits + num_spaces] = '\0';
  }
  return (const char *)B_complement;
}


//Decimal is converted to inverse
const char *D_to_B_inverse(int num){
  const char *B_complement = D_to_B_complement(num);
  if(num > 0) return B_complement;
  B_sub_one((char *)B_complement);
  return B_complement;
}

//Decimal is converted to original
const char *D_to_B_original(int num){
  const char *B_complement = D_to_B_complement(num);
  if(num > 0) return B_complement;
  B_original_to_B_inverse((char *)B_complement);
  B_add_one((char *)B_complement);
  return B_complement;
}

//原码转为反码(符号位不变其余位取反)
void B_original_to_B_inverse(char *B_original){
  int len = strlen(B_original)+1; //算上'\0'
  B_original++; //符号位不变
  while(*B_original != '\0'){
    if(*B_original == ' ') {
      *B_original = ' ';

      B_original++;
      continue;
    }
    *B_original = (*B_original == '1' ? '0':'1');
    B_original++;
  }
  B_original[len-1] = '\0';

}

void B_add_one(char *B){
  int len = strlen(B);
  for(int i=len-1;i>0;i--){ //符号位不变
    if (B[i] == ' ')
    {
      continue;
    }
    else if(B[i] == '1'){
      B[i] = '0';
    }
    else if(B[i] == '0'){
      B[i] = '1';
      break;
    }
  }
}

void B_sub_one(char *B){
  int len = strlen(B);
  for(int i=len-1;i>0;i--){ //符号位不变
    if (B[i] == ' ')
    {
      continue;
    }
    else if(B[i] == '1'){
      B[i] = '0';
      break;
    }
    else if(B[i] == '0'){
      B[i] = '1';
    }
  }
}

/**
  * @brief Complement code converted to decimal
  * @param "1111_1111" (Pass it a Complement string containing only 0s and 1s, and return the decimal value)
  * @retval decimal
  */
int B_complement_to_D(const char *str){
  if (str == NULL) return 0;
  unsigned char i = 1;
  int ans = 0;
  ans = -(str[0] - '0');
  while(str[i] != '\0'){
    if(str[i] == ' '){
        i++;
        continue;
    }
    ans = ans * 2 + (str[i] - '0');
    i++;
  }
  printf("%d \n",ans);
  return ans;
}


//原码转十进制
/**
  * @brief Binary code converted to decimal
  * @param "1111_1111" (Pass it a binary string containing only 0s and 1s, and return the decimal value)
  * @retval decimal
  */
int B_original_to_D(const char *str){
  if (str == NULL) return 0;
  unsigned char sign, i = 1;
  int ans = 0;
  sign = str[0] == '1' ? 1 : 0;
  while(str[i] != '\0'){
    if(str[i] == ' '){
        i++;
        continue;
    }
    ans = ans * 2 + (str[i] - '0');
    i++;
  }
  ans = sign ? -ans : ans;
  printf("%d \n",ans);
  return ans;
}


//判断两个无符号整数相加是否溢出
int uadd_ok(unsigned x,unsigned y){
  unsigned sum = x + y;
  return sum >= x;
}


//判断两个有符号整数相加是否溢出
int tadd_ok(int x,int y){
  int sum = x + y;
  int neg_over = x < 0 && y < 0 && sum >= 0;
  int pos_over = x >= 0 && y >= 0 && sum < 0;
  return !neg_over && !pos_over;
}


/*Determine whether arguments can be multiplied without overflow*/
int tmult_ok(int x,int y){
  int p = x * y;
  /*Either x is zero, or dividing p by x gives y*/
  return !x || p/x == y;
}



/**
 * @brief  将float的IEEE 754格式转换为十进制
 *         Value = (-1)^s x 1.M x 2^(e-Bias)
 *
 *         s: sign 符号位
 * 
 *         M: significand 二进制小数
 * 
 *         e: 实际存储值
 * 
 *         Bias: 偏置值
 * 
 *         (e-Bias): exponent 浮点数加权,以偏置形式表示的有符号整数
 *
 * @param  "1  0111 1110  0111 0011 0011 0011 0011 010" 示例输入
 * @retval 其十进制数
 */
double IEEE_conversion(const char *f_IEE,int exp_Bit_len,int Bias){
  //The sign bit is 0 for positive and 1 for negative
  int sign = f_IEE[0];
  int e=0;
  double significand=1;
  char exponent_B[exp_Bit_len+1];  //'\0'
  exponent_B[exp_Bit_len] = '\0';
  int i=1,exp_index = 0,significand_index = 1;

  while(f_IEE[i] != '\0'){
      if(f_IEE[i] != '1' && f_IEE[i] != '0'){
          i++;
      }else{
          if(exp_index < exp_Bit_len) {
              exponent_B[exp_index++] = f_IEE[i++];
          }
          else {
              significand += (f_IEE[i] - '0') * pow(2,-significand_index);
              i++;
              significand_index++;
          }
      }
  }


  for(int i=0;i<exp_Bit_len;i++){
      e += (exponent_B[i] - '0') * pow(2,exp_Bit_len - 1 - i);
  }


  //printf("e:%d , significand: %f \n",e,significand);
  double F_to_D = (significand) * pow(2,e-Bias);
  return sign ? -F_to_D : F_to_D;
}



float float_IEEE_conversion_to_D(const char *f_IEE){
  return (float)IEEE_conversion(f_IEE,8,127);
}



double double_IEEE_conversion_to_D(const char *f_IEE){
  return IEEE_conversion(f_IEE,11,1023);
}